package com.fivefu.core.hik.services.impl;

import com.alibaba.fastjson.JSON;
import com.fivefu.base.common.utils.str.StrUtils;
import com.fivefu.core.hik.constant.HikRequestTypeEnum;
import com.fivefu.core.hik.dto.request.*;
import com.fivefu.core.hik.dto.response.*;
import com.fivefu.core.hik.entity.DbHikDevice;
import com.fivefu.core.hik.entity.DbHikRegions;
import com.fivefu.core.hik.services.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class DeviceServiceImpl implements DeviceService {

    @Autowired
    private HikvisionService hikvisionService;

    @Autowired
    private DbHikDeviceService dbHikDeviceService;

    @Autowired
    private DbHikRegionsService dbHikRegionsService;

    @Autowired
    private DbHikRegionsDeviceService dbHikRegionsDeviceService;

    /**
     * 查询编码设备列表v2
     *
     */
    @Override
    public void searchEncodeDevice() {
        Integer pageNo = 1;
        Integer pageSize = 1000;
        List<String> deviceIndexCodes = new ArrayList<>();
        getEncodeDevice(pageNo,pageSize,deviceIndexCodes);
        //删除多余的海康设备数据
        dbHikDeviceService.deleteHikDevice(deviceIndexCodes,"sys");
    }

    /**
     * 查询编码设备列表v2
     * @param pageNo  当前页码
     * @param pageSize   分页大小
     * @param deviceIndexCodes
     */
    public void getEncodeDevice(Integer pageNo, Integer pageSize, List<String> deviceIndexCodes) {
        //查询编码设备列表V2必需参数
        PageReq pageReq = new PageReq(pageNo,pageSize);
        //将请求对象转换为json字符串
        String body = JSON.toJSONString(pageReq);

        //查询类型枚举
        HikRequestTypeEnum typeEnum = HikRequestTypeEnum.ENCODEDEVICEV2;

        //调用接口
        ResponseResult result = hikvisionService.doPostString(typeEnum.getUrl(), body, null, null, typeEnum.getType());
        ResponsePage resultPage = new ResponsePage();
        if (null != result && "0".equals(result.getCode())) {
            //调用成功
            String resultData = result.getData().toString();
            if (StrUtils.isNotNull(resultData)) {
                resultPage = JSON.parseObject(resultData, ResponsePage.class);

                resultPage.getList().forEach(deviceObj -> {
                    EncodeDeviceSearchResult encodeDeviceSearchResult = JSON.parseObject(JSON.toJSONString(deviceObj), EncodeDeviceSearchResult.class);
                    DbHikDevice device = encodeDeviceSearchResult.replaceDbHikDevice();
                    //编辑编码设备信息
                    dbHikDeviceService.editHikEncodeDevice(device);
                    deviceIndexCodes.add(device.getIndexCode());
                });

                //循环查询分页数据
                if (resultPage.getTotal() > ((pageNo - 1) * pageSize + pageSize)){
                    //调用方法本身，递归完成查询
                    getEncodeDevice(pageNo + 1,pageSize, deviceIndexCodes);
                }
            }
        }
    }

    /**
     * 查询编码设备列表v2
     * @param pageNo  当前页码
     * @param pageSize   分页大小
     */
    public void getEncodeDevice(Integer pageNo, Integer pageSize, boolean bol) {
        //查询编码设备列表V2必需参数
        PageReq pageReq = new PageReq(pageNo,pageSize);
        //将请求对象转换为json字符串
        String body = JSON.toJSONString(pageReq);

        //查询类型枚举
        HikRequestTypeEnum typeEnum = HikRequestTypeEnum.ENCODEDEVICEV;

        //调用接口
        ResponseResult result = hikvisionService.doPostString(typeEnum.getUrl(), body, null, null, typeEnum.getType());
        ResponsePage resultPage = new ResponsePage();
        if (null != result && "0".equals(result.getCode())) {
            //调用成功
            String resultData = result.getData().toString();
            if (StrUtils.isNotNull(resultData)) {
                resultPage = JSON.parseObject(resultData, ResponsePage.class);

                resultPage.getList().forEach(deviceObj -> {
                    EncodeDeviceSearchResult encodeDeviceSearchResult = JSON.parseObject(JSON.toJSONString(deviceObj), EncodeDeviceSearchResult.class);
                    DbHikDevice device = encodeDeviceSearchResult.replaceDbHikDevice();
                    //编辑编码设备信息
                    dbHikDeviceService.editHikEncodeDevice(device);
                });

                //循环查询分页数据
                if (resultPage.getTotal() > ((pageNo - 1) * pageSize + pageSize)){
                    //调用方法本身，递归完成查询
                    getEncodeDevice(pageNo + 1,pageSize,bol);
                }
            }
        }
    }

    /**
     * 根据区域获取下级编码设备列表
     *
     */
    @Override
    public void subResourcesEncodeDevice() {
        Integer pageNo = 1;
        Integer pageSize = 1000;
        //查询未删除区域唯一标识集合
        List<String> regionIDs = dbHikRegionsService.queryRegionIDs();
        //查询区域编码设备Map集合
        Map<String, Map<String, Long>> regionMap = dbHikRegionsDeviceService.queryRegionDeviceRegionMap();

        List<String> removeList = new ArrayList<>();
        //循环查询区域编码设备关联关系
        for (String regionIndexLogo : regionIDs) {
            //获取区域下所有编码设备资源唯一编码集合
            List<String> deviceList = queryDeviceByRegionIndexCode(pageNo,pageSize,regionIndexLogo);

            if (regionMap.containsKey(regionIndexLogo)) {
                Map<String, Long> deviceIndexCodeMap = regionMap.get(regionIndexLogo);
                Set<String> deviceIndexCodeSet = deviceIndexCodeMap.keySet();

                //已添加编码设备关联信息
                List<String> addedList = deviceIndexCodeSet.stream().filter(deviceIndexCode -> deviceList.contains(deviceIndexCode)).collect(Collectors.toList());
                //去掉已存在的编码设备
                List<String> addList = addedList.stream().filter(deviceIndexCode -> deviceList.contains(deviceIndexCode)).collect(Collectors.toList());
                deviceList.removeAll(addList);

                List<Long> regionDeviceIds = new ArrayList<>();
                deviceIndexCodeSet.removeAll(addedList);
                //删除多余编码设备
                for (String deviceIndexCode : deviceIndexCodeSet) {
                    Long regionDeviceId = deviceIndexCodeMap.get(deviceIndexCode);
                    regionDeviceIds.add(regionDeviceId);
                }
                if (!regionDeviceIds.isEmpty()) {
                    dbHikRegionsDeviceService.deleteRegionDevice(regionIndexLogo,regionDeviceIds);
                }
                removeList.add(regionIndexLogo);
            }
            //新增编码设备关联
            if (!deviceList.isEmpty()) {
                dbHikRegionsDeviceService.insertRegionDevices(regionIndexLogo,deviceList);
                removeList.add(regionIndexLogo);
            }
        }
        //删除其他区域关联关系
        regionIDs.removeAll(removeList);
        dbHikRegionsDeviceService.deleteNotContainRegionsDeviceByRegionIndexCodes(regionIDs);
    }

    /**
     * 获取区域下所有编码设备资源唯一编码集合
     * @param pageNo  当前页码
     * @param pageSize   分页大小
     * @param regionIndexCode  区域编号唯一标识
     * @return
     */
    private List<String> queryDeviceByRegionIndexCode(Integer pageNo, Integer pageSize, String regionIndexCode) {
        List<String> deviceList = new ArrayList<>();
        //根据区域获取下级编码设备列表必需请求参数
        EncodeDeviceSubResourcesReq encodeDeviceSubResources = new EncodeDeviceSubResourcesReq(regionIndexCode,pageNo,pageSize);
        //将请求对象转换为json字符串
        String body = JSON.toJSONString(encodeDeviceSubResources);
        //查询类型枚举
        HikRequestTypeEnum typeEnum = HikRequestTypeEnum.ENCODEDEVICEV1;

        //调用接口
        ResponseResult result = hikvisionService.doPostString(typeEnum.getUrl(), body, null, null, typeEnum.getType());
        if (null != result && "0".equals(result.getCode())) {
            //海康接口调用成功
            String resultData = result.getData().toString();
            if (StrUtils.isNotNull(resultData)) {
                ResponsePage reslutPage = JSON.parseObject(resultData, ResponsePage.class);

                reslutPage.getList().forEach(obj -> {
                    //JSONObject obj1 = JSON.parseObject(JSON.toJSONString(obj));
//                    if (obj1.containsKey("password")){
//                        System.out.println(obj1.getString("userName"));
//                        System.out.println(obj1.getString("password"));
//                    }

                    //System.out.println(JSON.toJSONString(obj));
                    EncodeDeviceSubResourcesResp encodeDeviceSubResourcesResp = JSON.parseObject(JSON.toJSONString(obj),EncodeDeviceSubResourcesResp.class);
                    deviceList.add(encodeDeviceSubResourcesResp.getIndexCode());
                });

                //循环查询分页数据
                if (reslutPage.getTotal() > ((pageNo -1 ) * pageSize + pageSize)) {
                    List<String> childList = queryDeviceByRegionIndexCode(pageNo + 1,pageSize,regionIndexCode);
                    deviceList.addAll(childList);
                }
            }
        }
        return deviceList;
    }

    /**
     * 增量获取编码设备数据
     * @param sTime  查询开始时间
     */
    @Override
    public void timeRangeEncodeDevice(String sTime) {
        Integer pageNo = 1;
        Integer pageSize = 1000;
        getTimeRangeEncodeDevice(sTime,pageNo,pageSize);
    }

    /**
     * 增量获取编码设备数据
     * @param sTime 查询开始时间
     * @param pageNo 当前页码
     * @param pageSize  分页大小
     */
    public void getTimeRangeEncodeDevice(String sTime,Integer pageNo, Integer pageSize) {
        EncodeDeviceTimeRangeReq encodeDeviceTimeRange = new EncodeDeviceTimeRangeReq(sTime,pageNo,pageSize);
        //将请求对象转换为json字符串
        String body = JSON.toJSONString(encodeDeviceTimeRange);
        //查询类型枚举
        HikRequestTypeEnum typeEnum = HikRequestTypeEnum.ENCODEDEVICEINCREMENT;

        //调用接口
        ResponseResult result = hikvisionService.doPostString(typeEnum.getUrl(), body, null, null, typeEnum.getType());
        ResponsePage resultPage = new ResponsePage();

        if (null != result && "0".equals(result.getCode())) {
            //调用成功
            String resultData = result.getData().toString();
            if (StrUtils.isNotNull(resultData)) {
                resultPage = JSON.parseObject(resultData,ResponsePage.class);

                resultPage.getList().forEach(deviceObj -> {
                    EncodeDeviceTimeRangeResp encodeDeviceTimeRangeResp = JSON.parseObject(JSON.toJSONString(deviceObj),EncodeDeviceTimeRangeResp.class);
                    DbHikDevice device = encodeDeviceTimeRangeResp.replaceDbHikDevice();
                    //编辑编码设备信息
                    dbHikDeviceService.editHikEncodeDevice(device);
                });

                //循环查询分页数据
                if (resultPage.getTotal() > ((pageNo - 1) * pageSize + pageSize)) {
                    //调用方法本身，递归完成查询
                    getTimeRangeEncodeDevice(sTime,pageNo + 1,pageSize);
                }
            }
        }
    }

    /**
     * 获取区域下所有编码设备资源唯一编码集合  汇总用的
     * @param pageNo  当前页码
     * @param pageSize   分页大小
     * @param regionIndexCode  区域编号唯一标识
     * @return
     */
    @Override
    public List<EncodeDeviceSubResourcesResp> queryAllDeviceByRegionIndexCode(Integer pageNo, Integer pageSize, String regionIndexCode) {
        List<EncodeDeviceSubResourcesResp> deviceList = new ArrayList<>();
        //根据区域获取下级编码设备列表必需请求参数
        EncodeDeviceSubResourcesReq encodeDeviceSubResources = new EncodeDeviceSubResourcesReq(regionIndexCode,pageNo,pageSize);
        //将请求对象转换为json字符串
        String body = JSON.toJSONString(encodeDeviceSubResources);
        //查询类型枚举
        HikRequestTypeEnum typeEnum = HikRequestTypeEnum.ENCODEDEVICEV1;

        //调用接口
        ResponseResult result = hikvisionService.doPostString(typeEnum.getUrl(), body, null, null, typeEnum.getType());
        if (null != result && "0".equals(result.getCode())) {
            //海康接口调用成功
            String resultData = result.getData().toString();
            if (StrUtils.isNotNull(resultData)) {
                ResponsePage reslutPage = JSON.parseObject(resultData, ResponsePage.class);

                reslutPage.getList().forEach(obj -> {
                    EncodeDeviceSubResourcesResp encodeDeviceSubResourcesResp = JSON.parseObject(JSON.toJSONString(obj),EncodeDeviceSubResourcesResp.class);
                    deviceList.add(encodeDeviceSubResourcesResp);
                });

                //循环查询分页数据
                if (reslutPage.getTotal() > ((pageNo -1 ) * pageSize + pageSize)) {
                    List<EncodeDeviceSubResourcesResp> childList = queryAllDeviceByRegionIndexCode(pageNo + 1,pageSize,regionIndexCode);
                    deviceList.addAll(childList);
                }
            }
        }
        return deviceList;
    }
}
